package com.sprouting.ops.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sprouting.ops.annotations.invoke.IdempotentSingle;
import com.sprouting.ops.interfaces.AddGroup;
import com.sprouting.ops.interfaces.ConstantBase;
import com.sprouting.ops.interfaces.UpdGroup;
import com.sprouting.ops.model.*;
import com.sprouting.ops.model.qo.OpsCommonUseAllQo;
import com.sprouting.ops.model.qo.OpsCommonUseQo;
import com.sprouting.ops.model.vo.OpsCommonUseTree;
import com.sprouting.ops.model.vo.OpsCommonUseVo;
import com.sprouting.ops.service.*;
import com.sprouting.ops.utils.CheckTool;
import com.sprouting.ops.utils.EntityTool;
import com.sprouting.ops.utils.IdTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 现场文件(OpsSiteFile)() 表控制层
 *
 * @author ：lx（长沙麓谷）
 * @date 创建时间：2025-03-24 18:11:44
 */
@Slf4j
@RestController
@RequestMapping("commonUse")
public class OpsCommonUseController {

    @Resource
    private OpsCommonUseService opsCommonUseService;
    @Resource
    private DromaraFileStorageService dromaraFileStorageService;
    @Resource
    private OpsSiteService opsSiteService;
    @Resource
    private OpsAppService opsAppService;
    @Resource
    private OpsComponentService opsComponentService;
    @Resource
    private OpsProductService opsProductService;


    /**
     * 管理员查询全部的常用文件
     * @param query 查询全部
     * @return
     */
    @PostMapping("getAllCommonUseList")
    public ResultJson getAllCommonUseList(OpsCommonUseAllQo query){
        if (query == null){
            query = new OpsCommonUseAllQo();
        }
        Page<OpsCommonUseVo> pageList = opsCommonUseService.getAllCommonUseList(query.getPage(), query);
        List<OpsCommonUseVo> records = pageList.getRecords();
        if (CollUtil.isEmpty(records)){
            return ResultJson.success(pageList);
        }

        List<String> bindIdList = records.stream().map(OpsCommonUseVo::getBindId).collect(Collectors.toList());
        List<OpsSite> siteList = opsSiteService.listByIds(bindIdList);
        List<OpsApp> appList = opsAppService.listByIds(bindIdList);
        List<OpsComponent> componentList = opsComponentService.listByIds(bindIdList);
        List<OpsProduct> productList = opsProductService.listByIds(bindIdList);

        // 转换为 key-id -> 名称
        Map<String, String> map = new HashMap<>();
        Optional.ofNullable(siteList).orElse(Collections.emptyList()).forEach(site -> map.put(site.getId(), site.getName()));
        Optional.ofNullable(appList).orElse(Collections.emptyList()).forEach(app -> map.put(app.getId(), app.getName()));
        Optional.ofNullable(componentList).orElse(Collections.emptyList()).forEach(component -> map.put(component.getId(), component.getName()));
        Optional.ofNullable(productList).orElse(Collections.emptyList()).forEach(product -> map.put(product.getId(), product.getName()));

        for (OpsCommonUseVo record : records) {
            record.setBindName(map.get(record.getBindId()));
        }

        return ResultJson.success(pageList);
    }

    /**
     * 分页查询常用文件
     * @param query 查询参数
     * @return
     */
    @PostMapping("getListPage")
    public ResultJson getListPage(OpsCommonUseQo query){
        Page page = query.getPage();
        return ResultJson.success(opsCommonUseService.getListPage(page, query));
    }

    /**
     * 模糊查询常用文件树
     * @param query 查询参数
     * @return
     */
    @PostMapping("getCommonUseTree")
    public ResultJson getCommonUseTree(@Validated OpsCommonUseQo query){
        List<OpsCommonUse> list = opsCommonUseService.getByBindId(query.getBindId());
        if (CollUtil.isEmpty(list)){
            return ResultJson.success();
        }

        List<OpsCommonUseTree> treeList = BeanUtil.copyToList(list, OpsCommonUseTree.class);

        // 排列成树
        List<OpsCommonUseTree> rootTree = buildTree(treeList);

        // 处理，过滤出name
        filterTreeByName(rootTree, query.getName());

        return ResultJson.success(rootTree);
    }

    /**
     * 删除常用文件
     * @param id 现场文件id
     * @return
     */
    @PostMapping("delCommonUse")
    @IdempotentSingle
    public ResultJson delCommonUse(String id){
        if (CheckTool.checkNull(id)){
            return ResultJson.errorCheck();
        }

        OpsCommonUse db = opsCommonUseService.getById(id);
        if (db == null){
            return ResultJson.success();
        }

        List<OpsCommonUse> sonList = opsCommonUseService.getBySonList(db.getId());
        if (CollUtil.isNotEmpty(sonList)){
            return ResultJson.error("存在下级文件，需要先删除下级文件后才能操作");
        }

        DromaraFileStorage unifiedFileInfo = dromaraFileStorageService.delFileBefore(db.getFileId());
        opsCommonUseService.delOpsSiteFile(id, unifiedFileInfo);
        return ResultJson.success();
    }

    /**
     * 更新常用文件
     * @param bo 修改参数
     * @return
     */
    @PostMapping("updCommonUse")
    @IdempotentSingle
    public ResultJson updCommonUse(@Validated(UpdGroup.class) OpsCommonUse bo){
        String msg = checkOpsSiteFile(bo);
        if (msg != null){
            return ResultJson.error(msg);
        }

        // 不允许修改这里
        bo.setParentIds(null);
        bo.setParentId(null);
        // 不能修改文件
        OpsCommonUse oldDb = opsCommonUseService.getById(bo.getId());
        DromaraFileStorage[] uploadFileArray = dromaraFileStorageService.updFileBefore(bo.getFileId(), oldDb.getFileId(), bo.getId(), ConstantBase.FileSourceType.SITE_FILE);

        EntityTool.updBase(bo);
        opsCommonUseService.updOpsSiteFile(bo, uploadFileArray);
        return ResultJson.success(bo);
    }

    /**
     * 保存现场文件
     * @param bo 保存参数
     * @return
     */
    @PostMapping("saveCommonUse")
    @IdempotentSingle
    public ResultJson saveCommonUse(@Validated(AddGroup.class) OpsCommonUse bo){
        String msg = checkOpsSiteFile(bo);
        if (msg != null){
            return ResultJson.error(msg);
        }

        bo.setId(IdTool.getId());
        EntityTool.saveBase(bo);

        // 添加上级部门
        String parentMsg = addParent(bo);
        if (parentMsg != null){
            return ResultJson.error(parentMsg);
        }

        // 处理文件
        DromaraFileStorage unifiedFileInfo = dromaraFileStorageService.toProductionBefore(bo.getFileId(), bo.getId(), ConstantBase.FileSourceType.SITE_FILE);
        opsCommonUseService.saveOpsSiteFile(bo, unifiedFileInfo);
        return ResultJson.success(bo);
    }


    /**
     * 现场文件数据校验
     * @param bo 现场文件 校验数据
     * @return 非null则有错误
     */
    private String checkOpsSiteFile(OpsCommonUse bo){
        if (!ConstantBase.DefaultValue.STRING.equals(bo.getParentId())){
            // 非顶级的时候要查询
            OpsCommonUse parent = opsCommonUseService.getById(bo.getParentId());
            if (ConstantBase.YesOrNo.NO.equals(parent.getFolder())){
                return "文件下面不能添加文件夹";
            }
        }
        if (ConstantBase.YesOrNo.NO.equals(bo.getFolder())){
            // 是文件的时候
            if (CheckTool.checkNull(bo.getFileId())){
                return "必须上传一个文件";
            }
        }

        if (bo.getSecrecy() == null){
            bo.setSecrecy(ConstantBase.YesOrNo.NO);
        }
        if (bo.getCore() == null){
            bo.setCore(ConstantBase.YesOrNo.NO);
        }
        return null;
    }

    /**
     * 添加上级部门
     * @param siteFile 文件信息
     * @return 非null则添加的时候出错了
     */
    private String addParent(OpsCommonUse siteFile){
        if (ConstantBase.DefaultValue.STRING.equals(siteFile.getParentId())){
            // 最上级
        } else {
            // 存在上级
            OpsCommonUse parent = opsCommonUseService.getById(siteFile.getParentId());
            if (parent == null){
                log.error("上级部门错误，不存在的上级。{}", siteFile.getParentId());
                return "非法上级部门";
            }

            if (StrUtil.isEmpty(parent.getParentIds())){
                // 上级节点是顶级节点，没有上级，直接填上级即可
                siteFile.setParentIds(parent.getId());
            } else {
                siteFile.setParentIds(parent.getParentIds() + "," + parent.getId());
            }
        }

        return null;
    }

    /**
     * 构建生成树
     * @param treeList 所有文件
     * @return 生成的树
     */
    private List<OpsCommonUseTree> buildTree(List<OpsCommonUseTree> treeList){
        if (CollUtil.isEmpty(treeList)){
            return null;
        }
        // 获取到根节点
        List<OpsCommonUseTree> rootList = treeList.stream().filter(i -> ConstantBase.DefaultValue.STRING.equals(i.getParentId())).sorted(Comparator.comparing(OpsCommonUseTree::getCreateTime)).collect(Collectors.toList());
        if (CollUtil.isEmpty(rootList)){
            log.error("[权限] 当前权限树异常，未查询到当前系统顶级节点!用户ID->{}", StpUtil.getLoginId());
            return null;
        }

        for (OpsCommonUseTree tree : rootList){
            getChild(tree, treeList);
        }

        return rootList;
    }

    /**
     * 获取文件子节点
     * @param tree 当前文件
     * @param treeList 全部文件
     */
    private void getChild(OpsCommonUseTree tree, List<OpsCommonUseTree> treeList){
        List<OpsCommonUseTree> childList = treeList.stream().filter(obj -> tree.getId().equals(obj.getParentId())).sorted(Comparator.comparing(OpsCommonUseTree::getCreateTime)).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(childList)){
            tree.setChildren(childList);

            for (OpsCommonUseTree siteFile : childList){
                siteFile.setParentName(tree.getParentName());
                getChild(siteFile, treeList);
            }
        }
    }

    /**
     * 根据名称过滤查询
     * @param treeList 要查询的树
     * @param keyword 匹配关键字
     */
    private void filterTreeByName(List<OpsCommonUseTree> treeList, String keyword) {
        if (CollUtil.isEmpty(treeList)){
            return ;
        }
        if (CheckTool.checkNull(keyword)){
            return ;
        }

        recursiveQuery(treeList, keyword);
    }

    /**
     * 递归方法
     * @param list 任意层级的节点
     * @param keyword 关键字
     */
    private void recursiveQuery(List<OpsCommonUseTree> list, String keyword) {
        Iterator<OpsCommonUseTree> parent = list.iterator();
        while (parent.hasNext()){
            // 当前节点
            OpsCommonUseTree itemTree = parent.next();
            if (itemTree.getName().contains(keyword)) {
                // 当前节点包含关键字，继续递归遍历
                // 子节点递归如果不包含关键字则会进入if分支被删除
                List<OpsCommonUseTree> children = itemTree.getChildren();
                // 递归
                if (CollUtil.isNotEmpty(children)) {
                    recursiveQuery(children, keyword);
                }

            } else {
                // 当前节点不包含关键字，继续遍历下一级
                // 取出下一级节点
                List<OpsCommonUseTree> children = itemTree.getChildren();
                // 递归
                if (CollUtil.isNotEmpty(children)) {
                    recursiveQuery(children, keyword);
                }
                // 下一级节点都被移除了，那么父节点也移除，因为父节点也不包含关键字
                if (CollUtil.isEmpty(itemTree.getChildren())) {
                    parent.remove();
                }
            }
        }
    }
}
